package com.xxcxcxcx.jobsystem.common.capability;

import com.ibm.icu.math.BigDecimal;
import com.xxcxcxcx.jobsystem.PlayerSaveData;
import com.xxcxcxcx.jobsystem.common.JobsClass;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.util.INBTSerializable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class JobCapability implements INBTSerializable<CompoundTag>, PlayerSaveData {
    protected Player player;

    protected HashMap<String, Integer> experienceCD = new HashMap<>();
    protected HashMap<String, Integer> level = new HashMap<>();
    protected HashMap<String, Double> experience = new HashMap<>();
    protected HashMap<String, Double> coefficient = new HashMap<>();
    protected boolean changeLevel = true;
    protected boolean readGainExperience = false;
    /**经验衰减系数为0.9^AttenuationTimes*/
    protected int attenuationTimes = 0;

    //速度经验获取
    public int speedTime = 0;
    public int saveMessage = 0;
    public Vec3 oldPos = null;

    public JobCapability(Player player) {
        this.player = player;
    }

    @Override
    public boolean isReadGainExperience() {
        return this.readGainExperience;
    }

    @Override
    public void setReadGainExperience(boolean value) {
        this.readGainExperience = value;
    }

    @Override
    public int getExperienceCD(String job) {
        if(!this.experienceCD.containsKey(job)) {
            return 0;
        }
        return this.experienceCD.get(job);
    }

    @Override
    public void setExperienceCD(String job, int cd) {
        if(this.experienceCD.containsKey(job)) {
            this.experienceCD.replace(job, cd);
        } else {
            this.experienceCD.put(job, cd);
        }
    }

    @Override
    public int getLevel(String job) {
        this.level.putIfAbsent(job, 0);
        return this.level.get(job);
    }

    @Override
    public double getExperience(String job) {
        this.experience.putIfAbsent(job, 0.0);
        return this.experience.get(job);
    }

    @Override
    public double getCoefficient(String job) {
        return getBaseCoefficient(job)*Math.pow(0.9,getAttenuationTimes());
    }
    public double getBaseCoefficient(String job) {
        this.coefficient.putIfAbsent(job, 1.0);
        return this.coefficient.get(job);
    }

    @Override
    public void setLevel(String job, int level) {
        if(level < 0) {
            return;
        }
        if(this.level.get(job) == null) {
            this.level.put(job, level);
        } else {
            this.level.replace(job, level);
        }
        setChange(true);
    }

    @Override
    public void setExperience(String job, double experience) {
        if(this.experience.get(job) == null) {
            this.experience.put(job, experience);
        } else {
            this.experience.replace(job, experience);
        }
    }

    @Override
    public void setCoefficient(String job, double coefficient) {
        BigDecimal bd = new BigDecimal(coefficient);
        coefficient = bd.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        if(this.coefficient.get(job) == null) {
            this.coefficient.put(job, coefficient);
        } else {
            this.coefficient.replace(job, coefficient);
        }
        if(this.coefficient.get(job) == 0.0) {
            this.coefficient.replace(job, 1.0);
        }
    }

    @Override
    public void addLevel(String job, int level) {
        setLevel(job, level + getLevel(job));
    }

    @Override
    public void addExperience(String job, double experience) {
        setExperience(job, experience + getExperience(job));
    }

    @Override
    public void addCoefficient(String job, double coefficient) {
        setCoefficient(job, coefficient + getCoefficient(job));
    }

    @Override
    public boolean canChange() {
        return this.changeLevel;
    }

    @Override
    public void setChange(boolean canChange) {
        this.changeLevel = canChange;
    }

    @Override
    public void setAttenuationTimes(int time) {
        this.attenuationTimes = time;
    }

    @Override
    public int getAttenuationTimes() {
        return this.attenuationTimes;
    }

    @Override
    public CompoundTag serializeNBT() {
        CompoundTag tag = new CompoundTag();
        tag.putBoolean("readGainExperience", isReadGainExperience());
        tag.putInt("readattenuationTimes", getAttenuationTimes());
        for(String i : JobsClass.Jobs) {
            CompoundTag jobParameter = new CompoundTag();
            jobParameter.putInt("level", getLevel(i));
            jobParameter.putDouble("experience", getExperience(i));
            jobParameter.putDouble("coefficient", getBaseCoefficient(i));
            tag.put(i, jobParameter);
        }
        return tag;
    }

    @Override
    public void deserializeNBT(CompoundTag nbt) {
        setReadGainExperience(nbt.getBoolean("readGainExperience"));
        setAttenuationTimes(nbt.getInt("readattenuationTimes"));
        for(String i : JobsClass.Jobs) {
            if(!nbt.contains(i)) {
                continue;
            }
            CompoundTag jobParameter = nbt.getCompound(i);
            setLevel(i, jobParameter.getInt("level"));
            setExperience(i, jobParameter.getDouble("experience"));
            setCoefficient(i, jobParameter.getDouble("coefficient"));
        }
    }

    public HashMap<String, Integer> getExperienceCD() {
        return this.experienceCD;
    }

    public HashMap<String, Integer> getLevel() {
        HashMap<String, Integer> s =new HashMap<>();
        for(String ss:JobsClass.Jobs){
            s.put(ss,getLevel(ss));
        }
        return s;
    }

    public HashMap<String, Double> getExperience() {
        HashMap<String, Double> s =new HashMap<>();
        for(String ss:JobsClass.Jobs){
            s.put(ss,getExperience(ss));
        }
        return s;
    }

    public HashMap<String, Double> getCoefficient() {
        HashMap<String, Double> c=new HashMap<>();
        for(String ss:JobsClass.Jobs){
            c.put(ss,getCoefficient(ss));
        }
        return c;
    }

    public void tickChange() {
        List<String> stringList=new ArrayList<>();
        for(String i : this.experienceCD.keySet()) {
            this.experienceCD.replace(i, this.experienceCD.get(i) - 1);
            if(this.experienceCD.get(i) == 0) {
                stringList.add(i);
            }
        }
        for(String s:stringList){
            this.experienceCD.remove(s);
        }
    }
}
